package common;

import javabot.JNIBWAPI;

public class Statistics {

	JNIBWAPI bwapi;

	private Player self, enemy; //Ruimte maken voor spelers
	private ArrayList<Unit> minerals, geysers; //Ruimte maken voor grondstoffen
	private Hashtable<Integer, UnitType> unitTable; //Ruimte maken voor units
	private int EnemyUnitScore, EnemyBuildingScore, EnemyMineralScore, EnemyTotalScore; //Ruimte maken voor scores
	private ArrayList<Integer> unitScore, buildingScore, mineralScore, totalScore; //Ruimte maken voor bijhouden scores

	public Statistics(JNIBWAPI bwapi) {
		this.bwapi = bwapi;
	} 

	public void gameStarted() {
		bwapi.enableUserInput(); //Bot mag gecorrigeerd worden door mensen
		bwapi.setGameSpeed(0); //Spel zo snel mogelijk maken
		bwapi.loadMapData(true); //Gegevens over het level inladen
		bwapi.enablePerfectInformation(); //Gegevens van tegenstander toestaan

		minerals = new ArrayList<Unit>(); //Lege lijst maken
		geysers = new ArrayList<Unit>(); //Lege lijst maken
		unitTable = new Hashtable<Integer, UnitType>(); //Lege tabel maken
		
		unitScore = new ArrayList<Integer>(); //Lege lijst maken
		buildingScore = new ArrayList<Integer>(); //Lege lijst maken
		mineralScore = new ArrayList<Integer>(); //Lege lijst maken
		totalScore = new ArrayList<Integer>(); //Lege lijst maken
		
		self = bwapi.getSelf(); //Gegevens van bot opzoeken
		enemy = bwapi.getEnemies().get(0); //Gegevens van tegenstander opzoeken
	}
	
	public void gameUpdate() {
		if (bwapi.getFrameCount() < 3) //Als spel net begonnen is
			return; //Nog niets doen

		if (bwapi.getFrameCount() == 3) //Als spel 3 frames heeft gespeeld
			getReferences(); //Data gaan verzamelen over spel

		calculateScores(); //Scores berekenen
	}
	
	private void getReferences(){
		for (Unit u : bwapi.getAllUnits()) { //Alle units bekijken
			UnitType type = bwapi.getUnitType(u.getTypeID()); //Type opvragen

			if (u.getPlayerID() == enemy.getID()) { //Unit van tegenstander?
				if (type.isBuilding()) //Unit is gebouw?
					EnemyBuildingScore += type.getBuildScore(); //Punten voor gebouw
				else //Unit is geen gebouw
					EnemyUnitScore += type.getBuildScore(); //Punten voor unit
			}
			
			if (u.getPlayerID() == self.getID()) //Unit van bot?
				unitTable.put(u.getID(), type); //ID en type opslaan

			if (u.getTypeID() == UnitTypes.Resource_Mineral_Field.ordinal()) //Unit is mineraal?
				minerals.add(u); //Opslaan in lijst
			
			if (u.getTypeID() == UnitTypes.Resource_Vespene_Geyser.ordinal()) //Unit is gas?
				geysers.add(u); //Opslaan in lijst
		}
	}

	public void calculateScores() {
		int MineralScore = 100; //Compenseren voor startwaarden
		
		for (int i = 0; i < minerals.size(); i++) //Door alle mineralen kijken
			MineralScore += minerals.get(i).getInitialResources() - minerals.get(i).getResources(); //Totaal gemijnde mineralen optellen

		for (int i = 0; i < geysers.size(); i++) //Door alle geisers kijken
			MineralScore += geysers.get(i).getInitialResources() - geysers.get(i).getResources(); //Totaal gemijnde gas optellen

		EnemyMineralScore = MineralScore - self.getCumulativeMinerals() - self.getCumulativeGas(); //Zelf gemijnde grondstoffen van totaal afhalen
		EnemyTotalScore = EnemyUnitScore + EnemyBuildingScore + EnemyMineralScore; //Totaalscore berekenen

		unitScore.add(EnemyUnitScore); //Score voor units opslaan in lijst
		buildingScore.add(EnemyBuildingScore); //Score voor gebouwen ""
		mineralScore.add(EnemyMineralScore); //Score voor mineralen ""
		totalScore.add(EnemyTotalScore); //Totaalscore ""
	}
	
	public void gameEnded() {
		try { //Probeer, voorkomt crash
			FileWriter fw = new FileWriter("test.csv", false); //Nieuw bestand, overschrijven
			fw.write("US,BS,MS,TS\r\n"); //Titels boven kolom zetten

			for (int i = 0; i < unitScore.size(); i++) { //Door alle data kijken
				String line = unitScore.get(i).toString() + ","; //Unit score
				line += buildingScore.get(i).toString() + ","; //Gebouw score
				line += mineralScore.get(i).toString() + ","; //Mineraal score
				line += totalScore.get(i).toString() + "\r\n"; //Totaal score

				fw.write(line); //Alle scores opschrijven
				fw.flush(); //Regel opslaan in bestand
			}
			fw.close(); //Bestand sluiten
		} catch (Exception e) { //Als het schrijven mislukt
			e.printStackTrace(); //Error tonen
		}
	}
	
	public void unitCreate(int unitID) {
		Unit u = bwapi.getUnit(unitID); //Gegevens opvragen
		UnitType type = bwapi.getUnitType(u.getTypeID()); //Type unit opvragen

		if (u.getPlayerID() == enemy.getID()) { //Unit van tegenstander?
			if (type.isBuilding()) //Is type gebouw?
				EnemyBuildingScore += type.getBuildScore(); //Punten voor gebouw
			else //Geen gebouw
				EnemyUnitScore += type.getBuildScore(); //Punten voor unit
		}

		if (u.getPlayerID() == self.getID()) //Unit van bot?
			unitTable.put(u.getID(), type); //Opslaan in tabel
	}
	
	public void unitDestroy(int unitID) {
		if (unitTable.containsKey(unitID)) { //Unit was van bot?
			UnitType type = unitTable.get(unitID); //Type ophalen uit tabel
			
			if (type.isBuilding()) //Unit was gebouw?
				EnemyBuildingScore += type.getDestroyScore(); //Punten voor gebouw
			else //Unit was geen gebouw
				EnemyUnitScore += type.getDestroyScore(); //Punten voor unit

			unitTable.remove(unitID); //Unit verwijderen uit tabel
		}
	}
	
	public void unitMorph(int unitID) {
		Unit u = bwapi.getUnit(unitID); //Gegevens opvragen
		UnitType type = bwapi.getUnitType(u.getTypeID()); //Type unit opvragen
		RaceType rt = bwapi.getRaceType(type.getRaceID()); //Ras opvragen

		if (rt.getID() == RaceTypes.Zerg.getID()){ //Als ras 'Zerg' is
			if (u.getPlayerID() == enemy.getID()) { //Unit van tegenstander?
				if (type.isBuilding()) //Unit is gebouw?
					EnemyBuildingScore += type.getBuildScore(); //Punten voor gebouw
				else //Unit is geen gebouw
					EnemyUnitScore += type.getBuildScore(); //Punten voor unit
			}
			if (u.getPlayerID() == self.getID()) //Unit van bot?
				unitTable.put(u.getID(), type); //Opslaan in tabel
		}
	}

	//public void connected() {}
	//public void keyPressed(int keyCode) {}
	//public void matchEnded(boolean winner) {}
	//public void nukeDetect(int x, int y) {}
	//public void nukeDetect() {}
	//public void playerLeft(int id) {}
	//public void unitDiscover(int unitID) {}
	//public void unitEvade(int unitID) {}
	//public void unitHide(int unitID) {}
	//public void unitShow(int unitID) {}
}